package com.xucy.springboot.designmodel.creational.single;

import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/**
 * @Author xucy
 * @Date 2019-07-17 09:41
 * @Description
 **/

public class TestHungry {
    public static void main(String[] args) throws IOException, ClassNotFoundException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {

        //测试序列化对单例的破坏，以及解决方案
//        testXLH();

        //反射创建对象  可以破坏单例模式
//        testReflect();
        //测试枚举 可防止反射和序列化破坏单例
//        testEnum();

        testStatic();
    }

    /**
     * 测试序列化对单例的破坏，以及解决方案
     *
     * @Author xucy
     * @Date 10:24 2019-07-17
     * @param
     * @return
     */
    public static void testXLH() throws IOException, ClassNotFoundException{
        //测试序列化与反序列化导致单例对象不一致的问题
        HungrySingleton hungrySingleton=HungrySingleton.getHungry();
        //com.xucy.springboot.designmodel.creational.single.HungrySingleton@3d646c37
        System.out.println(hungrySingleton);
        HungrySingleton hungrySingleton1=HungrySingleton.getHungry();
        //com.xucy.springboot.designmodel.creational.single.HungrySingleton@3d646c37
        System.out.println(hungrySingleton1);


        //输出对象
        ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("out.txt"));
        oos.writeObject(hungrySingleton);

        ObjectInputStream ios=new ObjectInputStream(new FileInputStream("out.txt"));
        HungrySingleton hungrySingleton2=(HungrySingleton)ios.readObject();
        //com.xucy.springboot.designmodel.creational.single.HungrySingleton@17d10166 与输出之前不一致
        //加了public Object readResolve() 可以保证返回的对象是同一个对象，这是因为调用ios.readObject()这个方法的时候，通过反射创建了一个新对象，但是他还是会判断这个
        //    类中是否有readResolve这个方法，如果有的话，就不返回反射创建的对象，而是直接返回 readResolve里面返回的对象
        System.out.println(hungrySingleton2);
    }
    /**
     *
     * 反射创建对象  可以破坏单例模式
     * @Author xucy
     * @Date 10:21 2019-07-17
     * @param
     * @return
     */
    public static void testReflect() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {

        Class cla=HungrySingleton.class;
        //获得类的构造方法
        Constructor constructor=cla.getDeclaredConstructor();
        //但是构造方法是私有的，所以不能newInstance，需要把构造方法升级
        constructor.setAccessible(true);

        HungrySingleton hungrySingleton=(HungrySingleton)constructor.newInstance();

        HungrySingleton hungrySingleton1=HungrySingleton.getHungry();

        //com.xucy.springboot.designmodel.creational.single.HungrySingleton@3cda1055
        System.out.println(hungrySingleton);
        //com.xucy.springboot.designmodel.creational.single.HungrySingleton@7a5d012c 反射和单例创建的对象不一致
        // 可以添加私有构造器中加异常，防止反射调用
        System.out.println(hungrySingleton1);
    }

    /**
     * 测试枚举类型 的单例模式
     *
     * @Author xucy
     * @Date 11:01 2019-07-17
     * @param
     * @return
     */
    public static void testEnum() throws IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        EnumSingleton enumSingleton=EnumSingleton.getInstance();

        ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("xtx.txt"));

        oos.writeObject(enumSingleton);

        ObjectInputStream ois=new ObjectInputStream(new FileInputStream("xtx.txt"));
        EnumSingleton enumSingleton1=(EnumSingleton)ois.readObject();

        System.out.println(enumSingleton);
        System.out.println(enumSingleton1);


        //防止反射
        Class cla=EnumSingleton.class;
        //enum没有空构造方法
        Constructor constructor=cla.getDeclaredConstructor();
        //反射不能初始化enum对象
        EnumSingleton enumSingleton2= (EnumSingleton)constructor.newInstance();
        System.out.println(enumSingleton2);
    }

    /**
     * 测试类的静态方法
     *
     * @Author xucy
     * @Date 14:14 2019-07-18
     * @param
     * @return
     */
    public static void testStatic(){
        Product.testStatic();

    }


}
